package com.cardone.platform.authority.util;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import com.cardone.common.template.util.TemplateUtils;
import com.cardone.context.ContextHolder;
import com.cardone.platform.authority.dto.NavigationDto;
import com.cardone.platform.authority.service.NavigationService;
import com.cardone.platform.configuration.dto.SiteDto;
import com.cardone.platform.configuration.util.SiteUtils;
import com.cardone.platform.usercenter.dto.UserDto;
import com.cardone.platform.usercenter.util.UserUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 导航工具类
 *
 * @author yaohaitao
 *
 */
public class NavigationUtils {
	/**
	 * 生成面包屑
	 *
	 * @param navigationList
	 *          导航集合
	 * @param navigation
	 *          导航
	 * @return 面包屑
	 */
	private static List<NavigationDto> buildBreadcrumb(final List<NavigationDto> navigationList, final NavigationDto navigation) {
		if (navigation == null) {
			return navigationList;
		}

		navigationList.add(0, navigation);

		return NavigationUtils.buildBreadcrumb(navigationList, navigation.getParentNavigation());
	}

	/**
	 * 查询:导航
	 *
	 * @param siteCode
	 *          站代码
	 * @param parentCode
	 *          导航代码
	 *
	 * @return 导航对象集合
	 */
	public static List<NavigationDto> findListByParentCodeForTree(final List<NavigationDto> navigationList, final String parentCode) {
		if (CollectionUtils.isEmpty(navigationList)) {
			return Lists.newArrayList();
		}

		for (final NavigationDto navigation : navigationList) {
			if (StringUtils.equals(parentCode, navigation.getCode())) {
				if (CollectionUtils.isEmpty(navigation.getChilds())) {
					return Lists.newArrayList();
				}

				return navigation.getChilds();
			}

			final List<NavigationDto> treeNavigationList = NavigationUtils.findListByParentCodeForTree(navigation.getChilds(), parentCode);

			if (!CollectionUtils.isEmpty(treeNavigationList)) {
				return treeNavigationList;
			}
		}

		return Lists.newArrayList();
	}

	/**
	 * 查询:导航
	 *
	 * @param siteCode
	 *          站代码
	 * @param parentId
	 *          导航标识
	 *
	 * @return 导航对象集合
	 */
	public static List<NavigationDto> findListByParentIdForTree(final List<NavigationDto> navigationList, final String parentId) {
		if (CollectionUtils.isEmpty(navigationList)) {
			return Lists.newArrayList();
		}

		for (final NavigationDto navigation : navigationList) {
			if (StringUtils.equals(parentId, navigation.getId())) {
				if (CollectionUtils.isEmpty(navigation.getChilds())) {
					return Lists.newArrayList();
				}

				return navigation.getChilds();
			}

			final List<NavigationDto> treeNavigationList = NavigationUtils.findListByParentIdForTree(navigation.getChilds(), parentId);

			if (!CollectionUtils.isEmpty(treeNavigationList)) {
				return treeNavigationList;
			}
		}

		return Lists.newArrayList();
	}

	/**
	 * 查询:导航
	 *
	 * @param siteCode
	 *          站代码
	 * @param parentCode
	 *          导航代码
	 * @param level
	 *          层级
	 *
	 * @return 导航对象集合
	 */
	public static List<NavigationDto> findListBySiteCodeAndParentCodeForTree(final String siteCode, final String parentCode, final int level) {
		return NavigationUtils.findListBySiteCodeAndTypeCodeAndParentCodeForTree(siteCode, null, parentCode, level);
	}

	/**
	 * 查询:导航
	 *
	 * @param siteCode
	 *          站代码
	 * @param parentId
	 *          导航标识
	 * @param level
	 *          层级
	 *
	 * @return 导航对象集合
	 */
	public static List<NavigationDto> findListBySiteCodeAndParentIdForTree(final String siteCode, final String parentId, final int level) {
		return NavigationUtils.findListBySiteCodeAndTypeCodeAndParentIdForTree(siteCode, null, parentId, level);
	}

	/**
	 * 查询:导航
	 *
	 * @param siteCode
	 *          站代码
	 * @param typeCode
	 *          类别代码
	 * @param parentCode
	 *          导航代码
	 * @param level
	 *          层级
	 * @return 导航对象集合
	 */
	public static List<NavigationDto> findListBySiteCodeAndTypeCodeAndParentCodeForTree(final String siteCode, final String typeCode, final String parentCode, final int level) {
		final List<NavigationDto> navigationList = ContextHolder.getBean(NavigationService.class).findListByParentCodeForTree(siteCode, typeCode, parentCode, level);

		return NavigationUtils.process(navigationList);
	}

	/**
	 * 查询:导航
	 *
	 * @param siteCode
	 *          站代码
	 * @param typeCode
	 *          类别代码
	 * @param parentId
	 *          导航标识
	 * @param level
	 *          层级
	 *
	 * @return 导航对象集合
	 */
	public static List<NavigationDto> findListBySiteCodeAndTypeCodeAndParentIdForTree(final String siteCode, final String typeCode, final String parentId, final int level) {
		final List<NavigationDto> navigationList = ContextHolder.getBean(NavigationService.class).findListByParentIdForTree(siteCode, typeCode, parentId, level);

		return NavigationUtils.process(navigationList);
	}

	/**
	 * 查询:导航 T
	 *
	 * @param siteCode
	 *          站代码
	 *
	 * @return 导航对象集合
	 */
	public static List<NavigationDto> findListForBreadcrumb(final List<NavigationDto> navigationList) {
		return NavigationUtils.findListForBreadcrumb(navigationList, SiteUtils.getContextSite().getRequestUri());
	}

	/**
	 * 查询:导航
	 *
	 * @param siteCode
	 *          站代码
	 * @param href
	 *          导航链接
	 *
	 * @return 导航对象集合
	 */
	public static List<NavigationDto> findListForBreadcrumb(final List<NavigationDto> navigationList, final String href) {
		if (CollectionUtils.isEmpty(navigationList)) {
			return Lists.newArrayList();
		}

		for (final NavigationDto navigation : navigationList) {
			if (StringUtils.equals(href, navigation.getHref())) {
				return NavigationUtils.buildBreadcrumb(new ArrayList<NavigationDto>(), navigation);
			}

			final List<NavigationDto> breadcrumbNavigationList = NavigationUtils.findListForBreadcrumb(navigation.getChilds(), href);

			if (!CollectionUtils.isEmpty(breadcrumbNavigationList)) {
				return breadcrumbNavigationList;
			}
		}

		return Lists.newArrayList();
	}

	/**
	 * 处理导航
	 *
	 * @param navigationList
	 *          导航集合
	 * @return 导航集合
	 */
	private static List<NavigationDto> process(final List<NavigationDto> navigationList) {
		if (CollectionUtils.isEmpty(navigationList)) {
			return navigationList;
		}

		final UserDto loginUser = UserUtils.findForLogin();

		final SiteDto contextSite = SiteUtils.getContextSite();

		return NavigationUtils.process(navigationList, null, loginUser, contextSite);
	}

	/**
	 * 处理导航
	 *
	 * @param navigationList
	 *          导航集合
	 * @param parentNavigation
	 *          父级导航
	 * @param user
	 *          上下文站
	 * @return 导航集合
	 */
	private static List<NavigationDto> process(final List<NavigationDto> navigationList, final NavigationDto parentNavigation, final UserDto user, final SiteDto contextSite) {
		if (CollectionUtils.isEmpty(navigationList)) {
			return navigationList;
		}

		for (int i = navigationList.size() - 1; i >= 0; i--) {
			final NavigationDto navigation = navigationList.get(i);

			navigation.setParentNavigation(parentNavigation);

			String href = StringUtils.defaultString(navigation.getUrl(), navigation.getCode());

			String url = StringUtils.replace(href, "${contextPath}", "${contextPath!}");

			url = TemplateUtils.processString(url, Maps.newHashMap());

			final boolean isAuthority = PermissionUtils.isUrlAuthority(user, url);

			if (!isAuthority) {
				navigationList.remove(i);

				continue;
			}

			href = TemplateUtils.processString(href, contextSite);

			navigation.setHref(href);

			if (StringUtils.equals(href, contextSite.getRequestUri())) {
				navigation.setActive(true);

				NavigationUtils.processParent(navigation);
			}

			if (!CollectionUtils.isEmpty(navigation.getChilds())) {
				NavigationUtils.process(navigation.getChilds(), navigation, user, contextSite);
			}
		}

		return navigationList;
	}

	/**
	 * 处理父级导航
	 *
	 * @param navigation
	 *          导航
	 */
	private static void processParent(final NavigationDto navigation) {
		if (navigation.getParentNavigation() == null) {
			return;
		}

		navigation.getParentNavigation().setActive(true);

		NavigationUtils.processParent(navigation.getParentNavigation());
	}
}